#pragma once

#include <iostream>
#include <cstdio>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <stdalign.h>
#include <unistd.h>
#include <string>
#include <string.h>

//路径
const std::string gpath = "/home/xzy/112/dir7";
//id
int gprojId = 0x6666;
//大小
int gshmsize = 4096;
//权限
mode_t gmode = 0600;

//内存共享公共类 
class ShareMemory
{
private:
    // 获取_shmid
    void CreateShmHelper(int shmflg)
    {
        // 获取_key
        key_t _key = ftok(gpath.c_str(), gprojId);
        if (_key == -1)
        {
            std::cerr << "ftok err" << std::endl;
            return;
        }

        std::cout<<_key<<std::endl;
        // 获取_shmid
        _shmid = shmget(_key, gshmsize, shmflg);
        std::cout<<_shmid<<std::endl;
        if (_shmid == -1)
        {
            std::cerr << "shmget err" << std::endl;
            return;
        }
    }

public:
    ShareMemory() : _shmid(-1), _key(0), _addr(nullptr) {}
    ~ShareMemory() {}
    // 创建共享内存
    void CreateShm()
    {
        if (_shmid == -1)
        {
            CreateShmHelper(IPC_CREAT | IPC_EXCL | gmode);
        }
    }

    // 获取共享内存
    void GetShm()
    {
        CreateShmHelper(IPC_CREAT);
    }

    // 将共享内存挂接到进程地址空间上建立映射关系
    void AttachShm()
    {
        _addr = shmat(_shmid, nullptr, 0);
    }

    // 解除映射关系
    void DetachShm()
    {
        int ret = shmdt(_addr);
        if (ret == -1)
        {
            std::cerr << "shmdt err" << std::endl;
        }
    }

    // 删除共享内存
    void DeleteShm()
    {
        int ret = shmctl(_shmid, IPC_RMID, nullptr);
        if (ret == -1)
        {
            std::cerr << "shmctl err" << std::endl;
        }
    }

    // 返回共享内存指针
    void *GetAddr()
    {
        return _addr;
    }

    // 共享内存的信息
    void ShmMeta()
    {
        shmid_ds ds; // 作为输出型参数
        int ret = shmctl(_shmid, IPC_STAT, &ds);
        if (ret == -1)
        {
            std::cerr << "shmctl err" << std::endl;
            return;
        }
    }

private:
    int _shmid; //shmid
    key_t _key; //key
    void *_addr;//指向进程地址的指针
};

ShareMemory shm;    //全局对象